/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package battleship.board;

import battleship.ship.DirectionEnum;
import battleship.ship.ShipType;
import java.util.ArrayList;
import java.util.List;
import util.MsgPrinter;

/**
 *
 * @author ali
 */
abstract public class AbstractBoardSide implements BoardSideType {

    final int WIDTH = 10;
    final int HEIGHT = 10;
    final int MAX_SHIP_COUNT = 2;
    LocationType[][] board = new Location[WIDTH][HEIGHT];
    List<ShipType> ships = new ArrayList<ShipType>();

    /**
     * Constructor
     */
    public AbstractBoardSide() {
        for (int i = 0; i < WIDTH; i++) {
            for (int j = 0; j < HEIGHT; j++) {
                board[i][j] = new Location();
            }
        }
    }

/**
 * This method validates the x and y. Then it marks the location on
 * the board as "HIT". Then it checks if the location at [x,y] contains
 * ship. If it does contain ship, it simply increments the actualHit counter on that ship.
 *
 * @param x
 * @param y
 * @return true, if the location was not previously hit.
 */
    public boolean hit(int x, int y) {
        //make sure that x and y are not outside the board limit.
        validateXandY(x, y);

        //Get the location at (x,y) on the board.
        LocationType location = board[x][y];
        //If the location is already hit, we cannot hit it again.
        boolean isAlreadyHit = location.isHit();
        boolean wasHitPossible = false;
        if (!isAlreadyHit) {
            //Since the location is not hit before, we can hit it.
            location.hit();//hit the location. Mark it as hit.
            wasHitPossible = true;

            //Check if this location also has any ship on it
            boolean containsShip = location.containsShip();

            //If there is a ship on this location, hit the ship
            if (containsShip) {
                //Decrement the possible hits for that ship.
                location.getShip().attemptHit(x, y);

            } else {
                MsgPrinter.print(getLocationString(x, y) + " location did not contain ship");
            }
        } else {
            MsgPrinter.print(getLocationString(x, y) + " location was already devasteted.");
        }
        return wasHitPossible;
    }

    private String getLocationString(int x, int y) {
        String locString = "[ " + Integer.toString(x) + ", " + Integer.toString(y) + " ]";
        return locString;
    }

    /**
     * @deprecated
     *
     * @param x
     * @param y
     * @return
     */
    private boolean didTheBombHitShip(int x, int y) {
        boolean didTheBombHitShip = false;
        boolean containsShip = board[x][y].containsShip();
        if (containsShip) {
            MsgPrinter.print("Ship hit");
        }

        return didTheBombHitShip;
    }

    /**
     *
     * @param x
     * @param y
     * @return true if the location at (x,y) was hit already.
     * @throws IllegalArgumentException
     */
    public boolean isHit(int x, int y) throws IllegalArgumentException {
        validateXandY(x, y);
        LocationType location = board[x][y];
        boolean isAlreadyHit = location.isHit();
        return isAlreadyHit;
    }

    public boolean setShip(ShipType ship, int x, int y) throws IllegalArgumentException, CannotPlaceShipException {
        if (!validateXandY(x, y)) {
            String hint = "x or y is wrong";
            throw new IllegalArgumentException(hint);
        }

        boolean success = false;
        //boolean canPlaceShip = canPlaceShip(ship, x, y);
        

            for (int i = 0; i < ship.getMAX_HITS_POSSIBLE(); i++) {
                LocationType location = null;
                if (ship.getDir().equals(DirectionEnum.HORIZONTAL)) {
                    location = board[x+i][y];
                } else {
                    location = board[x][y-i];
                }
                if (!location.containsShip()) {
                    success = location.setShip(ship);

                    if(!ships.contains(ship)){
                        ships.add(ship);
                    }
                }else{
                    String hint = "Location already contains ship.";
                    throw new CannotPlaceShipException(hint);
                }
            }
        

        return success;

    }

    private boolean canPlaceShip(ShipType ship, int x, int y) {
        boolean canPlace = true;
        for (int i = 0; i < ship.getMAX_HITS_POSSIBLE(); i++) {
            LocationType location = null;
            if (ship.getDir().equals(DirectionEnum.HORIZONTAL)) {
                location = board[i][y];
            } else {
                location = board[x][i];
            }
            if (location.containsShip()) {
                return false;
            }

        }
        return canPlace;
    }

    private boolean validateXandY(int x, int y) throws IllegalArgumentException {
        boolean isValid = true;
        if (x >= WIDTH || y >= HEIGHT || x < 0 || y < 0) {
            String hint = "x or y value is out of range";
            throw new IllegalArgumentException(hint);
        }
        return isValid;
    }

    /**
     * Simply returns the instance of list of ships
     * @return ships
     */
    public List<ShipType> getShips() {
        return ships;
    }

}
